package ru.usu.gv.gui.behavior;

import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupCondition;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOr;
import javax.vecmath.Vector3f;

import java.awt.AWTEvent;
import java.awt.event.KeyEvent;
import java.util.Enumeration;

/**
@author Sergey Pupyrev 
26.10.2008
*/

public class GVKeyNavigatorBehavior extends javax.media.j3d.Behavior
{
	private WakeupOnAWTEvent wakeupOne = null;
	private WakeupCriterion[] wakeupArray = new WakeupCriterion[1];
	private WakeupCondition wakeupCondition = null;
	private TransformGroup targetTG;
	private static final double TRANSLATE = 0.05d;

	public GVKeyNavigatorBehavior(TransformGroup tg)
	{
		targetTG = tg;

		wakeupOne = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
		wakeupArray[0] = wakeupOne;
		wakeupCondition = new WakeupOr(wakeupArray);
	}

	//Override Behavior's initialize method to set up wakeup criteria
	@Override
	public void initialize()
	{
		//Establish initial wakeup criteria
		wakeupOn(wakeupCondition);
	}

	//Override Behavior's stimulus method to handle the event.
	@Override
	public void processStimulus(Enumeration criteria)
	{
		WakeupOnAWTEvent ev;
		WakeupCriterion genericEvt;
		AWTEvent[] events;

		while (criteria.hasMoreElements())
		{
			genericEvt = (WakeupCriterion) criteria.nextElement();

			if (genericEvt instanceof WakeupOnAWTEvent)
			{
				ev = (WakeupOnAWTEvent) genericEvt;
				events = ev.getAWTEvent();
				processAWTEvent(events);
			}
		}

		//Set wakeup criteria for next time
		wakeupOn(wakeupCondition);
	}

	//Process a keyboard event
	private void processAWTEvent(AWTEvent[] events)
	{
		for (int n = 0; n < events.length; n++)
		{
			if (events[n] instanceof KeyEvent)
			{
				KeyEvent eventKey = (KeyEvent) events[n];
				if (eventKey.getID() == KeyEvent.KEY_PRESSED && isValidKeyEvent(eventKey))
				{
					performTransformChanges(eventKey);
				}
			}
		}
	}

	private void performTransformChanges(KeyEvent eventKey)
	{
		int keyCode = eventKey.getKeyCode();

		Vector3f translate = new Vector3f();

		Transform3D t3d = new Transform3D();
		targetTG.getTransform(t3d);
		t3d.get(translate);

		switch (keyCode)
		{
		case KeyEvent.VK_LEFT:
			translate.x += TRANSLATE;
			break;

		case KeyEvent.VK_RIGHT:
			translate.x -= TRANSLATE;
			break;

		case KeyEvent.VK_UP:
			translate.y -= TRANSLATE;
			break;

		case KeyEvent.VK_DOWN:
			translate.y += TRANSLATE;
			break;
		}

		t3d.setTranslation(translate);
		targetTG.setTransform(t3d);
	}

	private boolean isValidKeyEvent(KeyEvent keyEvent)
	{
		int keyCode = keyEvent.getKeyCode();

		switch (keyCode)
		{
		case KeyEvent.VK_UP:
			return true;
		case KeyEvent.VK_DOWN:
			return true;
		case KeyEvent.VK_LEFT:
			return true;
		case KeyEvent.VK_RIGHT:
			return true;
		}
		return false;
	}

}
